package com.ddxcloud.movie.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.ddxcloud.common.constants.ResultStatusConstant;
import com.ddxcloud.common.constants.enums.PayStatusEnum;
import com.ddxcloud.common.handler.BusinessException;
import com.ddxcloud.common.utils.IpUtil;
import com.ddxcloud.movie.config.wechat.WxPayConfiguration;
import com.ddxcloud.movie.data.dto.PayDTO;
import com.ddxcloud.movie.data.dto.WechatPayDTO;
import com.ddxcloud.movie.data.entity.PaymentOrder;
import com.ddxcloud.movie.mapper.PaymentOrderMapper;
import com.ddxcloud.movie.service.*;
import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Result;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Service
@Slf4j
public class WechatPayServiceImpl implements WechatPayService {

    @Resource
    PaymentOrderService paymentOrderService;

    @Resource
    PaymentOrderMapper paymentOrderMapper;

    @Resource
    OrderService orderService;

    @Resource
    WxPayService wxPayService;

    @Resource
    WxPayConfiguration wxPayConfiguration;

    @Override
    public <T> T createOrder(PayDTO dto, HttpServletRequest request) {
        PaymentOrder paymentOrder = paymentOrderService.createPaymentOrder(dto, request);
        if (ObjectUtil.isNotEmpty(paymentOrder)) {
            try {
                WxPayUnifiedOrderV3Request orderV3Request = new WxPayUnifiedOrderV3Request();
                orderV3Request.setOutTradeNo(paymentOrder.getOutTradeNo());
                orderV3Request.setDescription(paymentOrder.getProductName());
                orderV3Request.setTimeExpire(DateUtil.format(new Date(), "yyyy-MM-dd'T'HH:mm:ssXXX"));
                orderV3Request.setNotifyUrl(paymentOrder.getCallbackUrl());
                WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
                amount.setTotal(paymentOrder.getPayAmount());
                amount.setCurrency("CNY");
                orderV3Request.setAmount(amount);
                if (dto.getTradeType().equals(TradeTypeEnum.H5)) {
                    WxPayUnifiedOrderV3Request.SceneInfo sceneInfo = new WxPayUnifiedOrderV3Request.SceneInfo();
                    WxPayUnifiedOrderV3Request.H5Info h5Info = new WxPayUnifiedOrderV3Request.H5Info();
                    h5Info.setType("Wap");
                    h5Info.setAppName("订单熊");
                    h5Info.setAppUrl("http://movie.ddx24.com");
                    sceneInfo.setH5Info(h5Info);
                    sceneInfo.setPayerClientIp(IpUtil.getClientIp(request));
                    orderV3Request.setSceneInfo(sceneInfo);
                    log.info("微信支付-响应参数 {}", JSONUtil.toJsonStr(orderV3Request));
                    String h5Url = wxPayService.createOrderV3(dto.getTradeType(), orderV3Request);
                    return (T) h5Url;
                } else if (dto.getTradeType().equals(TradeTypeEnum.JSAPI)) {
                    WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer();
                    payer.setOpenid(dto.getOpenId());
                    orderV3Request.setPayer(payer);
                    log.info("微信支付-响应参数 {}", JSONUtil.toJsonStr(orderV3Request));
                    WxPayConfig wxPayConfig=new WxPayConfig();
                    wxPayConfig.setAppId(wxPayConfiguration.getJsapiAppId());
                    wxPayConfig.setMchId(wxPayConfiguration.getMchId());
                    wxPayConfig.setApiV3Key(wxPayConfiguration.getApiV3key());
                    wxPayConfig.setPrivateKeyPath(wxPayConfiguration.getPrivateKeyPath());
                    wxPayConfig.setPrivateCertPath(wxPayConfiguration.getPrivateCertPath());

                    // 沙箱环境（V3版本不支持沙箱环境）
                    wxPayConfig.setUseSandboxEnv(false);
                    wxPayService.setConfig(wxPayConfig);
                    Object orderV3 = wxPayService.createOrderV3(dto.getTradeType(), orderV3Request);
                    log.info("微信支付-返回参数 {}", JSONUtil.toJsonStr(orderV3));
                    return (T) orderV3;
                }

            } catch (WxPayException e) {
                log.error("微信支付失败 {}", e.getMessage());
                throw new BusinessException(e.getMessage());
            }
        }
        return null;
    }

    @Override
    public <T> T createJsApi(WechatPayDTO wechatPayDto, HttpServletRequest request){

        log.info("获取openId-请求参数 {}", JSONUtil.toJsonStr(wechatPayDto));
        String url="https://api.weixin.qq.com/sns/oauth2/access_token?appid="+wxPayConfiguration.getJsapiAppId()+
                "&secret="+wxPayConfiguration.getJsapiSecret()+
                "&code="+wechatPayDto.getCode()+
                "&grant_type=authorization_code";
        log.info("获取openId-请求地址 {}", url);
        String body = HttpRequest.get(url).execute().body();
        log.info("获取openId-响应参数 {}", body);
        String openId=JSONUtil.parseObj(body).getStr("openid");
        PayDTO dto=new PayDTO();
        dto.setPayMethod(2);
        dto.setTradeType(TradeTypeEnum.JSAPI);
        dto.setOrderId(wechatPayDto.getOrderId());
        dto.setOpenId(openId);
        return this.createOrder(dto, request);
    }

    @Override
    public Map<String, String> notify(HttpServletRequest request, HttpServletResponse response) throws WxPayException, IOException {
        SignatureHeader signatureHeader = new SignatureHeader();
        signatureHeader.setTimeStamp(request.getHeader("Wechatpay-Timestamp"));
        signatureHeader.setNonce(request.getHeader("Wechatpay-Nonce"));
        signatureHeader.setSignature(request.getHeader("Wechatpay-Signature"));
        signatureHeader.setSerial(request.getHeader("Wechatpay-Serial"));
        String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
        WxPayNotifyV3Result notifyV3Result = wxPayService.parseOrderNotifyV3Result(xmlResult, signatureHeader);
        log.info("微信支付-回调 {}", JSONUtil.toJsonStr(notifyV3Result));

        // 取出订单ID
        String orderId = StringUtils.substringBeforeLast(notifyV3Result.getResult().getOutTradeNo(), "_");

        Map<String, String> resultMap = new HashMap<>();
        PaymentOrder paymentOrder = paymentOrderMapper.getOrderByOrderId(orderId);
        if (ObjectUtil.isNotNull(paymentOrder)) {
            if (Objects.equals(paymentOrder.getPayStatus(), PayStatusEnum.STATUS_1.getCode())) {
                resultMap.put("code", ResultStatusConstant.SUCCESS);
                resultMap.put("message", ResultStatusConstant.SUCCESS);
                return resultMap;
            }
            boolean res = paymentOrderService.updatePaymentOrderForPaySuccess(paymentOrder);
            if (res) {
                res = orderService.updateOrderForPaySuccess(orderId, paymentOrder, request);
                if (res) {
                    resultMap.put("code", ResultStatusConstant.SUCCESS);
                    resultMap.put("message", ResultStatusConstant.SUCCESS);
                }
            }
        } else {
            response.setStatus(400);
            resultMap.put("code", ResultStatusConstant.FAIL);
            resultMap.put("message", ResultStatusConstant.FAIL);
        }
        return resultMap;
    }
}
